﻿
Imports System.IO
Imports xmlctrl
Imports xhtmlctrl
Imports webctrl

Public Class filetraversal
    Inherits cacheControlProcessor

    Public Const _pathidentity As String = "/filetrav"
    Public Const query As String = "p"

    Protected Overrides Function normalRetiredTicks() As Long
        Return secondsToTicks(10)
    End Function

    Public Overrides Function pathidentity() As String
        Return _pathidentity
    End Function

    Private Function relativepath(ByRef s As String, ByVal path As String) As String
        If Not strendwith(path, filesystem.directorySeperator, False) Then
            path = path + filesystem.directorySeperator
        End If

        If strsame(s, path, strlen(path)) Then
            Return strmid(s, strlen(path))
        Else
            Return s
        End If
    End Function

    Protected Function generateBackToParent(ByVal context As httpContext, ByVal path As String) As a
        Dim a As a = Nothing
        a = context.createControl(New a())
        If Directory.Exists(path) Then
            a.href = network.parentPathMark
        ElseIf File.Exists(path) Then
            a.href = network.thislevelPathMark
        Else
            a.href = network.linkPositionMark
        End If
        a.text = "[back to parent folder]"
        Return a
    End Function

    Protected Overridable Function processDirectory(ByVal context As httpContext, _
                                                    ByVal path As String, ByRef control As xmlcontrol) As Boolean
        If Not strendwith(path, filesystem.directorySeperator, False) Then
            path += filesystem.directorySeperator
        End If

        Dim page As xhtmlpage = Nothing
        page = context.createControl(New xhtmlpage())

        Dim strs() As String = Nothing
        Try
            strs = Directory.GetDirectories(path)
        Catch ex As Exception
            raiseError("cannot get directories under " + path + ", ignore. ex " + ex.Message, _
                       errorHandle.errorType.warning)
            Dim label As label = Nothing
            label = context.createControl(New label())
            label.text = "cannot get sub directories."
            page.body().addchild(label)
            page.body().addchild(context.createControl(New br()))
        End Try

        Dim a As a = Nothing
        If Not strs Is Nothing AndAlso strs.Length() > 0 Then
            Dim i As Int32
            For i = 0 To strs.Length() - 1
                a = context.createControl(New a())
                a.href = relativepath(strs(i), path) + network.pathSeperator
                a.text = "[" + Convert.ToString(a.href) + "]"
                page.body().addchild(a)
                page.body().addchild(context.createControl(New br()))
            Next
        End If

        Try
            strs = Directory.GetFiles(path)
        Catch ex As Exception
            raiseError("cannot get files under " + path + ", ignore. ex " + ex.Message, _
                       errorHandle.errorType.warning)
            Dim label As label = Nothing
            label = context.createControl(New label())
            label.text = "cannot get sub files."
            page.body().addchild(label)
            page.body().addchild(context.createControl(New br()))
        End Try

        If Not strs Is Nothing AndAlso strs.Length() > 0 Then
            Dim i As Int32
            For i = 0 To strs.Length() - 1
                a = context.createControl(New a())
                a.href = relativepath(strs(i), path)
                a.text = a.href
                page.body().addchild(a)
                page.body().addchild(context.createControl(New br()))
            Next
        End If

        page.body().addchild(generateBackToParent(context, path))

        control = page
        Return True
    End Function

    Protected Overrides Function enableEmptyControl() As Boolean
        Return True
    End Function

    Protected Overridable Function processFile(ByVal context As httpContext, _
                                               ByVal path As String, ByRef control As xmlcontrol) As Boolean
        Dim bt As bytes = Nothing
        Try
            bt = File.ReadAllBytes(path)
        Catch ex As Exception
            raiseError("cannot read file " + path + ", ignore. ex " + ex.Message, errorHandle.errorType.warning)
            Return False
        End Try

        context.buff.Write(+bt, 0, bt.size)
        Return True
    End Function

    Protected Overridable Sub addpathResponseHeaders(ByVal context As httpContext)
        assert(Not context Is Nothing, "context is nothing.")
    End Sub

    Protected Overridable Sub addfileResponseHeaders(ByVal context As httpContext)
        assert(Not context Is Nothing, "context is nothing.")
        context.setcontentType(network.http.contentType.applicationOctetStream)
    End Sub

#If RETIRED Then
    Protected Overloads Sub addresponseHeaders(ByVal context As httpContext, _
                                               ByVal path As String)
        If isemptystring(path) Then
            raiseError("do not get valid path, ignore.", errorHandle.errorType.warning)
            Return
        End If

        If Directory.Exists(path) Then
            addpathResponseHeaders(context)
        ElseIf File.Exists(path) Then
            addfileResponseHeaders(context)
        Else
            raiseError("do not have dir / file in path " + path + ", ignore.", errorHandle.errorType.warning)
        End If
    End Sub

    Protected Overrides Sub addresponseHeaders(ByVal context As httpContext)
        MyBase.addresponseHeaders(context)
        assert(Not context Is Nothing, "context is nothing.")
        addresponseHeaders(context, context.url().query(query))
    End Sub
#End If

    Protected Overloads Function processImpl(ByVal context As httpContext, _
                                             ByVal path As String, ByRef control As xmlcontrol) As Boolean
        If isemptystring(path) Then
            raiseError("do not get valid path, ignore.", errorHandle.errorType.warning)
            Return False
        End If

        If Directory.Exists(path) Then
            addpathResponseHeaders(context)
            Return processDirectory(context, path, control)
        ElseIf File.Exists(path) Then
            addfileResponseHeaders(context)
            Return processFile(context, path, control)
        Else
            Return False
        End If
    End Function

    Protected Overrides Function processImpl(ByVal context As httpContext, ByRef control As xmlcontrol) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        Return processImpl(context, context.url().query(query), control)
    End Function
End Class
